package com.jqh.openglesdemo.shader;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.util.DisplayMetrics;
import android.util.Log;

import com.jqh.openglesdemo.R;
import com.jqh.openglesdemo.jqhopengl.GLSurfaceView;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

public class JqhTextureRender implements GLSurfaceView.GLRender {

    private Context context;

    // 绘制上半部分
//    private float[] vertexData = {
//            -1f, -1f,
//            1f, -1f,
//            -1f, 1f,
//            1f, 1f
//
//            -0.5f, -0.5f,
//            0.5f, -0.5f,
//            -0.5f, 0.5f,
//            0.5f, 0.5f
//    };

    // 多绘制，填入两次坐标
    private float[] vertexData = {
            -1f, -1f,
            1f, -1f,
            -1f, 1f,
            1f, 1f,

            -0.5f, -0.5f,
            0.5f, -0.5f,
            -0.5f, 0.5f,
            0.5f, 0.5f
    };

    private float[] fragmentData = {
            // fbo模式坐标
//            0f, 0f,
//            1f, 0f,
//            0f, 1f,
//            1f, 1f

            //  纹理模式坐标
            0f, 1f,
            1f, 1f,
            0f, 0f,
            1f, 0f
    };

    private FloatBuffer vertexBuffer ;

    private FloatBuffer fragmentBuffer;

    private int program ;
    private int vPosition; //  顶点
    private int fPosition; //  纹理

    private int textureId; // 纹理id

    private int sampler;

    // 顶点缓存数据
    private int vboId;

    // 帧缓存数据
    private int fboId;

    private int imgTextureId;

    private int imgTextureId2;

    private FboRender fboRedner;

    // 正交投影要使用的矩阵
    private int umatrix;

    private float[] matrix = new float[16];

    private int imageW, imageH;

    public JqhTextureRender(Context context) {
        this.context = context;
        fboRedner = new FboRender(context);
        vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(vertexData);
        vertexBuffer.position(0);

        fragmentBuffer = ByteBuffer.allocateDirect(fragmentData.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(fragmentData);
        fragmentBuffer.position(0);
    }

    @Override
    public void onSurfaceCreate() {
        fboRedner.onCreate();
        String vertexSource = JqhShaderUtils.getRawResource(context, R.raw.vertext_shader_m);
        String fragmentSource = JqhShaderUtils.getRawResource(context, R.raw.fragment_shader);

        program = JqhShaderUtils.createProgram(vertexSource, fragmentSource);

        // 10 得到着色器中的属性
        vPosition = GLES20.glGetAttribLocation(program, "v_Position");
        fPosition = GLES20.glGetAttribLocation(program, "f_Position");

        sampler = GLES20.glGetUniformLocation(program, "sTexture");

        umatrix = GLES20.glGetUniformLocation(program, "u_Matrix");

        // 利用vbo缓存顶点数据
        int [] vbos = new int[1];
        GLES20.glGenBuffers(1, vbos, 0);
        vboId = vbos[0];
        // 绑定vbo的id
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);
        // 分配缓存大小
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexData.length * 4 + fragmentData.length * 4, null, GLES20.GL_STATIC_DRAW);
        // 给分配的空间填充数据
        GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, vertexData.length * 4, vertexBuffer);
        GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, vertexData.length * 4, fragmentData.length * 4, fragmentBuffer);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

        // 利用fbo缓存帧数据
        int[] fbos = new int[1];
        GLES20.glGenBuffers(1, fbos, 0);
        fboId = fbos[0];
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboId);

        // 创建和绑定纹理
        int[] textureIds = new int[1];
        GLES20.glGenTextures(1, textureIds, 0);
        textureId = textureIds[0];
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glUniform1i(sampler, 0);

        // 设置纹理环绕方式
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
        // 设置纹理过滤方式
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);


        //  设置fbo大小
        DisplayMetrics outMetrics = new DisplayMetrics();
        ((Activity)context).getWindowManager().getDefaultDisplay().getRealMetrics(outMetrics);
        int widthPixel = outMetrics.widthPixels;
        int heightPixel = outMetrics.heightPixels;
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, widthPixel, heightPixel, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);

        // 把纹理绑定到帧缓存上, 后面对fbo的操作就是对纹理的操作
        GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, textureId, 0);

        if(GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER) != GLES20.GL_FRAMEBUFFER_COMPLETE){
            Log.e("JqhTextureRender", "fbo wrong");
        } else {
            Log.e("JqhTextureRender", "fbo success");
        }
        // 解绑纹理
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
        // 解绑帧缓存
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

        imgTextureId = loadTextrue(R.drawable.b);
        imgTextureId2 = loadTextrue(R.drawable.tupian);

        if (onRenderCreateListener != null) onRenderCreateListener.onCreate(textureId);
    }

    @Override
    public void onSurfaceChanged(int width, int height) {
        GLES20.glViewport(0,0, width, height);
        fboRedner.onChange(width, height);

        // 设置正交投影
        if(width > height) {
            // 横屏 高度填满 bottom -1   top 1
//            float left = -width / (height/imageH) * imageW;
            // 计算水平-1 到1之间的比例
            float xScale = width / (((height * 1.0f)/imageH) * imageW);
            Matrix.orthoM(matrix,0,-xScale, xScale,-1,1,-1, 1);
        } else {
            // 竖屏
            float yScale = height / (((width * 1.0f)/imageW) * imageH);
            Matrix.orthoM(matrix,0,-1, 1,-yScale,yScale,-1, 1);
        }

        // 旋转
        Matrix.rotateM(matrix, 0, 180, 1, 0, 0);

//        Matrix.rotateM(matrix, 0, 180, 0, 0, 1);
    }

    @Override
    public void onDrawFrame() {
        // 绑定帧缓存， 开启离屏显然
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboId);

        // 用颜色刷新
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glClearColor(1f, 0f, 0f,1f);
        // 11 使用源程序
        GLES20.glUseProgram(program);

        // 正交投影使用
        GLES20.glUniformMatrix4fv(umatrix, 1 ,false, matrix,0);

        // 绑定vbo
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId);


        // 以下进行多绘制

        //---start第一次绘制
        // 重新绑定纹理, 绑定到imgTextureId，然帧缓存来处理
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, imgTextureId);

        // 12 使得顶点属性数组有效
        GLES20.glEnableVertexAttribArray(vPosition);
        // 13 为顶点属性赋值
        GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8 , 0);



        // 14 使得纹理属性数组有效
        GLES20.glEnableVertexAttribArray(fPosition);
        // 15  为纹理属性赋值
        GLES20.glVertexAttribPointer(fPosition, 2, GLES20.GL_FLOAT, false, 8 , vertexData.length * 4);

        // 16 绘制图形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); // 最后一个参数设置绘制几个点
        //---------------end-------------------


        //-------------start 第二次绘制 渲染第二张图片----------------
        // 重新绑定纹理, 绑定到imgTextureId，然帧缓存来处理
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, imgTextureId2);

        // 12 使得顶点属性数组有效
        GLES20.glEnableVertexAttribArray(vPosition);
        // 13 为顶点属性赋值
        //  绘制第二张图片时，从32开始， vertexData 有16位，前8位是第一张图，后8位是第二张图，然后后8位要从  8*4 开始偏移
        GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 8 , 32);



        // 14 使得纹理属性数组有效
        GLES20.glEnableVertexAttribArray(fPosition);
        // 15  为纹理属性赋值
        GLES20.glVertexAttribPointer(fPosition, 2, GLES20.GL_FLOAT, false, 8 , vertexData.length * 4);

        // 16 绘制图形
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); // 最后一个参数设置绘制几
        //------------------end----------------


        //  解除绑定纹理
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);

        // 解除vbo绑定
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

        // fbo使用代码
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

        fboRedner.onDraw(textureId);

    }

    private int loadTextrue(int src){
        // 创建和绑定纹理
        int[] textureIds = new int[1];
        GLES20.glGenTextures(1, textureIds, 0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[0]);

        // 设置纹理环绕方式
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
        // 设置纹理过滤方式
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);

        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), src);
        imageH = bitmap.getHeight();
        imageW = bitmap.getWidth();
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
        bitmap.recycle();
        bitmap = null;

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
        return textureIds[0];
    }

    // 获取离屏渲染的id

    private OnRenderCreateListener onRenderCreateListener;

    public void setOnRenderCreateListener(OnRenderCreateListener onRenderCreateListener) {
        this.onRenderCreateListener = onRenderCreateListener;
    }

    public  interface OnRenderCreateListener{
        void onCreate(int textureId);
    }
}
